package com.ruoyi.service;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.ruoyi.common.core.domain.ActHiProcinstExt;
import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.mapper.ActHiProcinstExtMapper;
import com.ruoyi.common.core.mapper.SysDeptMapper;
import com.ruoyi.common.core.mapper.SysUserMapper;
import com.ruoyi.common.flowable.FlowServiceFactory;
import com.ruoyi.common.flowable.FlowableUtils;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.entity.SysForm;
import lombok.extern.slf4j.Slf4j;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.engine.repository.Deployment;
import org.flowable.task.api.Task;
import org.flowable.task.api.history.HistoricTaskInstance;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
import static com.ruoyi.common.utils.DateUtils.YYYY_MM_DD_HH_MM_SS;

/**
 * <p>工作流流程实例管理<p>
 *
 * @author XuanXuan
 *
 */
@Service
@Slf4j
public class FlowInstanceExtServiceImpl extends FlowServiceFactory {
    @Autowired
    private ActHiProcinstExtMapper actHiProcinstExtMapper;

    @Autowired
    private SysUserMapper sysUserMapper;

    @Autowired
    private SysDeptMapper sysDeptMapper;

    public void updateExt(String processInstanceId) {
        List<Task> tasks = taskService.createTaskQuery().processInstanceId(processInstanceId).list();
        updateExt(processInstanceId, tasks.size() > 0 ? tasks.get(0) : null,null);
    }

    public void updateExt(String processInstanceId, Task task,List<String> userIdList) {
        ActHiProcinstExt ext = actHiProcinstExtMapper.selectById(processInstanceId);
        HistoricProcessInstance pi = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
        Deployment deployment = repositoryService.createDeploymentQuery().deploymentId(pi.getDeploymentId()).singleResult();
        boolean isInsert = ext == null;
        if (ext == null) {
            SysForm sysForm = getSysFormMapper().getByDeployId(pi.getDeploymentId());
            ext = new ActHiProcinstExt();
            if (sysForm != null) {
                ext.setProcDefName(sysForm.getFormName());
            } else {
                ext.setProcDefName(deployment.getName());
            }
            ext.setProcDefKey(pi.getProcessDefinitionKey());
            ext.setTaskName(pi.getName());
            ext.setProcInstId(processInstanceId);
            ext.setDeployId(pi.getDeploymentId());

            SysUser sysUser = sysUserMapper.selectById(pi.getStartUserId());
            ext.setStartUserId(sysUser.getUserId());
            ext.setStartUserName(sysUser.getNickName());
            if (sysUser.getDeptId() != null) {
                SysDept sysDept = sysDeptMapper.selectById(sysUser.getDeptId());
                ext.setStartUserDept(sysDept.getDeptName());
            }
        }
        if (ext.getAttrs() == null) {
            ext.setAttrs(JSON.toJSONString(FlowableUtils.getNodesAttr(repositoryService.getBpmnModel(pi.getProcessDefinitionId()).getProcesses())));
        }
        if (task != null) {
            ext.setCurrTaskId(task.getId());
            if(userIdList != null && !userIdList.isEmpty()){
               List<SysUser> sysUsers = sysUserMapper.selectBatchIds(userIdList);
                ext.setCurrTaskAssignee(sysUsers.stream().map(r->r.getNickName()).collect(Collectors.joining(",")));
            }else{
                ext.setCurrTaskAssignee("");
            }
            ext.setCurrTaskNode(task.getName());

            HistoricTaskInstance historicTaskInstance = historyService.createHistoricTaskInstanceQuery().includeProcessVariables().finished().taskId(task.getId()).singleResult();
            Map<String, Object> variables;
            if (Objects.nonNull(historicTaskInstance)) {
                variables = historicTaskInstance.getProcessVariables();
            } else {
                variables = taskService.getVariables(task.getId());
            }
            if (variables != null) {
                ext.setVariable(JSON.toJSONString(variables));
                if(variables.containsKey("taskName")){
                    ext.setTaskName(variables.get("taskName").toString());
                }
            }

            ext.setCurrTaskCanEdit("false");
            ext.setCurrTaskKey(task.getTaskDefinitionKey());
            if (ext.getAttrs() != null) {
                JSONObject nodes = JSON.parseObject(ext.getAttrs());
                JSONObject node = nodes.getJSONObject(task.getTaskDefinitionKey());
                if (node != null && node.containsKey("canEdit")) {
                    ext.setCurrTaskCanEdit(node.get("canEdit").toString());
                }
            }
            ext.setCurrTaskCreatetime(DateUtils.parseDateToStr(YYYY_MM_DD_HH_MM_SS, task.getCreateTime()));
        } else {
            ext.setCurrTaskCanEdit("false");
            ext.setCurrTaskKey("End");
            ext.setCurrTaskCreatetime(DateUtils.getTime());
            ext.setCurrTaskId(" ");
            ext.setCurrTaskAssignee(" ");
            ext.setCurrTaskNode("结束");
        }
        ext.setFlowStatus(actHiProcinstExtMapper.getFlowStatus(processInstanceId));
        if (isInsert) {
            actHiProcinstExtMapper.insert(ext);
        } else {
            actHiProcinstExtMapper.updateById(ext);
        }

    }


}